package com.rtx.wcs.std.handle.wcstoris;

import java.time.LocalDateTime;
import java.util.List;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.rtx.wcs.std.bean.po.EdiTaskCallBackLog;
import com.rtx.wcs.std.bean.po.Loc;
import com.rtx.wcs.std.bean.po.RtxPalletcantilever;
import com.rtx.wcs.std.bean.po.TaskDetail;
import com.rtx.wcs.std.handle.ristowcs.AbsTaskDownHandle;
import com.rtx.wcs.std.service.EdiTaskCallBackLogService;
import com.rtx.wcs.std.service.LocService;
import com.rtx.wcs.std.service.RtxPalletcantileverService;
import com.rtx.wcs.std.service.TaskDetailService;
import com.rtx.wms.std.common.bean.Codelkup;
import com.rtx.wms.std.common.service.CommonService;

import cn.hutool.core.lang.UUID;
import cn.hutool.http.HttpRequest;


/**
 * 任务执行结果
 * @author Administrator
 *
 */
@Service("TaskCallBackHandle")
public class AbsTaskCallBackHandle implements TaskCallBackHandle{
	
	Logger logger = LoggerFactory.getLogger(AbsTaskDownHandle.class);
	
	@Autowired
	RtxPalletcantileverService rtxPalletcantileverService;
	
	@Autowired
	TaskDetailService taskDetailService;
	
	@Autowired
	EdiTaskCallBackLogService ediTaskCallBackLogService;
	
	@Autowired
	LocService locService;
	
	@Autowired
	CommonService commonService;
	
	ThreadPoolExecutor pool = new ThreadPoolExecutor(10, 100, 60, TimeUnit.SECONDS, new LinkedBlockingDeque<>(100));

	
	
	@Value("${riswms.move.std}")
	private String riswms_move_std;

	@Override
	public String handleTaskCallback(String wcsCallbackRequestStr) {
		JSONObject wcsResponse = new JSONObject();
		wcsResponse.put("code", "");
		wcsResponse.put("message", "");
		wcsResponse.put("reqCode", "");
		wcsResponse.put("data", "");
		

		EdiTaskCallBackLog log = null;
		try {
			//生成日志
			log =  createEdiTaskCallBackLog(wcsCallbackRequestStr);
			
			JSONObject wcsCallbackRequest = JSON.parseObject(wcsCallbackRequestStr);
			wcsResponse.put("reqCode", wcsCallbackRequest.get("reqCode"));
			wcsResponse.put("data", wcsCallbackRequest.get("reqCode"));
			
			//校验必填字段
			check(wcsCallbackRequest);

			//处理回传逻辑
			handleCallbackBytaskCode(wcsCallbackRequest,log);
			
			wcsResponse.put("code", "0");
			wcsResponse.put("message", "success");
		} catch (Exception e) {
			logger.error("任务执行结果-异常",e);
			wcsResponse.put("code", "1");
			wcsResponse.put("message", e.getMessage());
		}finally {
			log.setEdiresponse(wcsResponse.toJSONString());
			insertLogs(log);
		}
		
		
		
		return wcsResponse.toJSONString();
	}
	
	protected void insertLogs(EdiTaskCallBackLog log) {
		try {
			pool.execute(()->{
				ediTaskCallBackLogService.insertLog("ris_edi", log);
	        });
			
		} catch (Exception e) {
			logger.error("",e);
		}
	};
	
	/**
	 * 生成日志实体类
	 * @return
	 */
	protected EdiTaskCallBackLog createEdiTaskCallBackLog(String wcsRequest) {
		EdiTaskCallBackLog log = new EdiTaskCallBackLog();
		log.setApiname("WCS->WMS任务执行结果");
		log.setWcsrequest(wcsRequest);
		log.setWcsrequesturl("/v1/edi/task/callback");

		JSONObject request = JSON.parseObject(wcsRequest);
		log.setWhseid(request.getString("whseid"));
		log.setTaskcode(request.getString("taskcode"));
		log.setMethod(request.getString("method"));
		log.setTasktype(request.getString("tasktype"));
		log.setAdddate(LocalDateTime.now());
		
		return log;
	};
	
	
	//{"whseid":"仓库号","taskcode":"任务号","method":"方法名","tasktype":"任务类型"}
	protected void check(JSONObject request ) {
		Assert.hasLength(request.getString("whseid"), "whseid为必填字段");
		Assert.hasLength(request.getString("taskcode"), "taskcode为必填字段");
		Assert.hasLength(request.getString("method"), "method为必填字段");
		Assert.hasLength(request.getString("tasktype"), "tasktype为必填字段");
	}
	
	//根据返回的仓库号+当前任务单号查询RTX_PALLETCANTILEVER、TASKDETAIL表出对应数据
	protected void handleCallbackBytaskCode(JSONObject request,EdiTaskCallBackLog log) {
		String whseid = request.getString("whseid");
		String taskcode = request.getString("taskcode");
	
		
		LambdaQueryWrapper<RtxPalletcantilever> pquery = Wrappers.lambdaQuery();
		pquery.eq(RtxPalletcantilever::getTaskcode, taskcode);
		pquery.eq(RtxPalletcantilever::getWhseid, whseid);
		List<RtxPalletcantilever> pList = rtxPalletcantileverService.queryByCondition(whseid, pquery);
		
		//处理回调逻辑
		if(!CollectionUtils.isEmpty(pList)) {
			handlePalletcantilever(pList.get(0),request,log);
			return;
		}
		
		LambdaQueryWrapper<TaskDetail> tquery = Wrappers.lambdaQuery();
		tquery.eq(TaskDetail::getTaskcode, taskcode);
		tquery.eq(TaskDetail::getWhseid, whseid);
		List<TaskDetail> tList =taskDetailService.queryByCondition(whseid, tquery);
		
		//处理回调逻辑
		if(!CollectionUtils.isEmpty(tList)) {
			handleTaskdetail(tList.get(0),request,log);
		}

	}
	
	//	Method=start时，
	//			当taskcode在RTX_PALLETCANTILEVER表中时，更新RTX_PALLETCANTILEVER、表出对应数据，更新状态为3处理中
	//			当taskcode在TASKDETAIL表中时，任务类型（WZLKX，WZLCK，WZLHK，WZLBZHK）更新TASKDETAIL表对应数据，更新状态为3处理中
	//			Method=end时，
	//			当taskcode在RTX_PALLETCANTILEVER表中时，更新RTX_PALLETCANTILEVER表对应数据，状态为9已完成，并调用【标准移动】，将托盘/箱移动RTX_PALLETCANTILEVER.LOC
	//			当taskcode在TASKDETAIL表中时，任务类型（WZLKX，WZLCK，WZLHK，WZLBZHK）更新TASKDETAIL表对应数据，更新状态为9已完成，再执行以下逻辑：
	//			任务类型 = WZLKX，根据任务自库位，更新库位表LOC.LPN字段为空
	//			任务类型 = WZLCK，调用并调用【标准移动】，将箱移动至系统代码RTXWCSLOC，CODE = WCSUP,UDF1值的库位上
	//			任务类型 = WZLHK，调用并调用【标准移动】，箱移动至任务对应的至库位
	protected void handlePalletcantilever(RtxPalletcantilever p,JSONObject request,EdiTaskCallBackLog log) {
		String method = request.getString("method");
		String whseid = request.getString("whseid");
		
		LambdaUpdateWrapper<RtxPalletcantilever> upd = Wrappers.lambdaUpdate();
		if("start".equals(method)) {
			upd.set(RtxPalletcantilever::getStatus, "3");
			
			
		}else if("end".equals(method)) {
			upd.set(RtxPalletcantilever::getStatus, "9");
			
			String containerCode = request.getString("containerCode");
			JSONObject risrequest = new JSONObject();
			risrequest.put("containerCode", containerCode);
			risrequest.put("loc", p.getLoc());
			risrequest.put("whseid", whseid);
			
			//请求wms标准移动,失败则抛出异常
			callWMSAPI(risrequest,log);
			
			//再通过rtx_palletcantilever.loc更新库位表LOC.LPN字段为RTX_PALLETCANTILEVER.LPN
			LambdaUpdateWrapper<Loc> locUpd = Wrappers.lambdaUpdate();
			locUpd.eq(Loc::getLoc, p.getLoc());
			locUpd.set(Loc::getLpn,p.getLpn());
			locService.updBycondition(whseid, locUpd);
		}
		
		upd.eq(RtxPalletcantilever::getSerialkey, p.getSerialkey());
		rtxPalletcantileverService.updByCondition(whseid, upd);
	};
	
	
	
	
	//	Method=start时，
	//			当taskcode在RTX_PALLETCANTILEVER表中时，更新RTX_PALLETCANTILEVER、表出对应数据，更新状态为3处理中
	//			当taskcode在TASKDETAIL表中时，任务类型（WZLKX，WZLCK，WZLHK，WZLBZHK）更新TASKDETAIL表对应数据，更新状态为3处理中
	//			Method=end时，
	//			当taskcode在RTX_PALLETCANTILEVER表中时，更新RTX_PALLETCANTILEVER表对应数据，状态为9已完成，并调用【标准移动】，将托盘/箱移动RTX_PALLETCANTILEVER.LOC
	//			当taskcode在TASKDETAIL表中时，任务类型（WZLKX，WZLCK，WZLHK，WZLBZHK）更新TASKDETAIL表对应数据，更新状态为9已完成，再执行以下逻辑：
	//			任务类型 = WZLKX，根据任务自库位，更新库位表LOC.LPN字段为空
	//			任务类型 = WZLCK，调用并调用【标准移动】，将箱移动至系统代码RTXWCSLOC，CODE = WCSUP,UDF1值的库位上
	//			任务类型 = WZLHK，调用并调用【标准移动】，箱移动至任务对应的至库位
	protected void handleTaskdetail(TaskDetail taskDetail,JSONObject request,EdiTaskCallBackLog log) {
		String method = request.getString("method");
		String whseid = request.getString("whseid");
		
		LambdaUpdateWrapper<TaskDetail> upd = Wrappers.lambdaUpdate();
		if("start".equals(method)) {
			upd.set(TaskDetail::getStatus, "3");
			
		}else if("end".equals(method)) {
			upd.set(TaskDetail::getStatus, "9");
			
			String tasktype = taskDetail.getTasktype();
			

			if("WZLKX".equals(tasktype)) {
				LambdaUpdateWrapper<Loc> locUpd = Wrappers.lambdaUpdate();
				locUpd.eq(Loc::getLoc, taskDetail.getFromloc());
				locUpd.set(Loc::getLpn,"");
				locService.updBycondition(whseid, locUpd);
			}else if("WZLCK".equals(tasktype)) {
				
				LambdaQueryWrapper<Codelkup> lqw = Wrappers.lambdaQuery();
				lqw.eq(Codelkup::getListname, "RTXWCSLOC");
				lqw.eq(Codelkup::getCode, "WCSUP");
				List<Codelkup> configloc =	commonService.selectCodelkupByWrapper(whseid, lqw);
				
				
				String containerCode = request.getString("containerCode");
				JSONObject risrequest = new JSONObject();
				risrequest.put("containerCode", containerCode);
				risrequest.put("loc", configloc.get(0).getUdf1());
				risrequest.put("whseid", taskDetail.getWhseid());
			
				//请求wms标准移动,失败则抛出异常
				callWMSAPI(risrequest,log);
				
				//再通过taskDetail.loc更新库位表LOC.LPN字段为空
				LambdaUpdateWrapper<Loc> locUpd = Wrappers.lambdaUpdate();
				locUpd.eq(Loc::getLoc, taskDetail.getFromloc());
				locUpd.set(Loc::getLpn," ");
				locService.updBycondition(whseid, locUpd);
				
			}else if("WZLHK".equals(tasktype)) {
				String containerCode = request.getString("containerCode");
				JSONObject risrequest = new JSONObject();
				risrequest.put("containerCode", containerCode);
				risrequest.put("loc", taskDetail.getToloc());
				//请求wms标准移动,失败则抛出异常
				callWMSAPI(risrequest,log);
			}else if("PK".equals(tasktype)) {
				
			}
		}
		
		upd.eq(TaskDetail::getSerialkey, taskDetail.getSerialkey());
		taskDetailService.updByCondition(whseid, upd);
	};
	
	//调用riswms标准移动
	protected String callWMSAPI(JSONObject request,EdiTaskCallBackLog log) {
		String uuid = UUID.randomUUID().toString();
		String requestStr = request.toJSONString();
		log.setEdirequest(requestStr);
		log.setEdirequesturl(riswms_move_std);
		logger.info("uid-{}-taskcode-{}-任务执行结果-调用标准移动-请求报文-{}",uuid,log.getTaskcode(),requestStr);
		String	result = HttpRequest
				.post(riswms_move_std)
				.body(request.toJSONString())
				.timeout(30000)
				.execute()
				.body();
		logger.info("uid-{}-taskcode-{}-任务执行结果-调用标准移动-响应报文-{}",uuid,log.getTaskcode(),result);
		log.setRiswmsresponse(result);
		JSONObject res = JSON.parseObject(result);
		
		if(!"200".equals(res.getString("returnCode"))) {
			throw new RuntimeException(result);
		}
		return result;
	};
}
